package com.auto.survey.activity.monitoring.dao

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import com.auto.survey.activity.monitoring.entity.MonitoringObservation
import com.auto.survey.activity.monitoring.entity.MonitoringPoint
import com.auto.survey.activity.monitoring.entity.relations.MonitoringPointWithObservations
import kotlinx.coroutines.flow.Flow

/**
 * 测点数据访问对象接口
 * 定义与测点相关的数据库操作,
 */
@Dao
interface MonitoringPointDao {

    /**
     * 根据监测对象ID获取测点列表，按测量顺序排序
     * @param objectId 监测对象ID
     * @return 测点列表Flow流
     */
    @Query("SELECT * FROM MonitoringPoint WHERE monitoringObjectId = :objectId ORDER BY measurementOrder ASC")
    fun getMonitoringPointsByObjectId(objectId: Int): Flow<List<MonitoringPoint>>

    @Query("SELECT * FROM MonitoringPoint WHERE monitoringObjectId = :objectId AND pointType = :pintType ORDER BY measurementOrder ASC")
    fun getCtrlPointsByObjectIdAndType(objectId: Int, pintType:String): Flow<List<MonitoringPoint>>

    /**
     * 根据监测对象ID并且已经采集获取测点列表，按测量顺序排序
     * @param objectId 监测对象ID
     * @return 测点列表Flow流
     */
    @Query("SELECT * FROM MonitoringPoint WHERE monitoringObjectId = :objectId AND collected = true ORDER BY measurementOrder ASC")
    fun getMonitoringPointsCollectedByObjectId(objectId: Int): Flow<List<MonitoringPoint>>

    @Query("SELECT COUNT(*) FROM MonitoringPoint WHERE monitoringObjectId = :objectId AND collected = true")
    fun getPointClloectedCountByObjectId(objectId: Int):Int

    @Query("SELECT COUNT(*) FROM MonitoringPoint WHERE stationId = :stationId AND collected = true")
    fun getPointClloectedCountByStationId(stationId: Int):Int


    /**
     * 根据测点ID获取测点信息
     * @param id 测点ID
     * @return 测点实体或null
     */
    @Query("SELECT * FROM MonitoringPoint WHERE id = :id")
    suspend fun getMonitoringPointById(id: Int): MonitoringPoint?

    /**
     * 插入新测点
     * @param point 测点实体
     * @return 插入的测点ID
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertMonitoringPoint(point: MonitoringPoint): Long

    /**
     * 批量插入测点
     * @param points 测点列表
     * @return 插入的测点ID列表
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertMonitoringPoints(points: List<MonitoringPoint>): List<Long>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertObserv(observ: MonitoringObservation):Long

    /**
     * 更新测点信息
     * @param point 测点实体
     */
    @Update
    suspend fun updateMonitoringPoint(point: MonitoringPoint)

    /**
     * 删除测点
     * @param point 测点实体
     */
    @Delete
    suspend fun deleteMonitoringPoint(point: MonitoringPoint)

    /**
     * 根据测点ID删除测点
     * @param id 测点ID
     */
    @Query("DELETE FROM MonitoringPoint WHERE id = :id")
    suspend fun deleteMonitoringPointById(id: Int)

    /**
     * 根据监测对象ID获取测点数量
     * @param objectId 监测对象ID
     * @return 测点数量
     */
    @Query("SELECT COUNT(*) FROM MonitoringPoint WHERE monitoringObjectId = :objectId")
    suspend fun getMonitoringPointCountByObjectId(objectId: Int): Int

    /**
     * 获取监测对象下的最大测量顺序号
     * @param objectId 监测对象ID
     * @return 最大测量顺序号或null(如果没有测点)
     */
    @Query("SELECT MAX(measurementOrder) FROM MonitoringPoint WHERE monitoringObjectId = :objectId")
    suspend fun getMaxMeasurementOrder(objectId: Int): Int?

    /**
     * 调整测量顺序，将指定监测对象下大于等于startOrder的测量顺序号加1
     * 用于插入新测点时调整顺序
     * @param monitoringId 监测对象ID
     * @param startOrder 起始顺序号
     */
    @Query("UPDATE MonitoringPoint SET measurementOrder = measurementOrder + 1 WHERE monitoringObjectId = :objectId AND measurementOrder >= :startOrder")
    suspend fun shiftMeasurementOrders(objectId: Int, startOrder: Int)

    /**
     * 根据测点ID获取测点及其关联的观测数据
     * @param pointId 测点ID
     * @return 包含观测数据的测点数据类
     */
    @Transaction
    @Query("SELECT * FROM MonitoringPoint WHERE id = :pointId")
    suspend fun getMonitoringPointWithObservations(pointId: Int): MonitoringPointWithObservations?

    /**
     * 获取监测对象下的所有测点及其关联的观测数据
     * @param objectId 监测对象ID
     * @return 包含观测数据的测点列表Flow流
     */
    @Transaction
    @Query("SELECT * FROM MonitoringPoint WHERE monitoringObjectId = :objectId")
    fun getPointsWithObservationsByMonitoringId(objectId: Int): Flow<List<MonitoringPointWithObservations>>

    /**
     * 根据站点ID获取测点列表，按测量顺序排序
     * @param stationId 站点ID
     * @return 测点列表Flow流
     */
    @Query("SELECT * FROM MonitoringPoint WHERE stationId = :stationId ORDER BY measurementOrder ASC")
    fun getMonitoringPointsByStationId(stationId: Int): Flow<List<MonitoringPoint>>

    /**
     * 根据站点ID获取已采集数据的测点列表
     * @param stationId 站点ID
     * @return 已采集的测点列表Flow流
     */
    @Query("SELECT * FROM MonitoringPoint WHERE stationId = :stationId AND collected = true ORDER BY measurementOrder ASC")
    fun getCollectedPointsByStationId(stationId: Int): Flow<List<MonitoringPoint>>

    /**
     * 根据站点ID和测点类型获取测点列表
     * @param stationId 站点ID
     * @param pointType 测点类型（控制点、测点）
     * @return 测点列表Flow流
     */
    @Query("SELECT * FROM MonitoringPoint WHERE stationId = :stationId AND pointType = :pointType ORDER BY measurementOrder ASC")
    fun getPointsByStationIdAndType(stationId: Int, pointType: String): Flow<List<MonitoringPoint>>

}